
// supplemental includes from memp.c

//#define MEMP_SIZE           0
//
#define MEMP_SANITY_REGION_BEFORE_ALIGNED    0
#define MEMP_SANITY_REGION_AFTER_ALIGNED     0
//#define MEMP_SIZE          (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED)
//#define MEMP_SIZE          (LWIP_MEM_ALIGN_SIZE(100))

//#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED)

/**
 * Get an element from a specific pool.
 *
 * @param type the pool to get an element from
 *
 * the debug version has two more parameters:
 * @param file file name calling this function
 * @param line number of line where this function is called
 *
 * @return a pointer to the allocated memory or a NULL pointer on error
 */
//typedef u8_t sys_prot_t;

void *
memp_malloc(memp_t type)
{
  struct memp *memp;
  SYS_ARCH_DECL_PROTECT(old_level);
 
  //LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);

  SYS_ARCH_PROTECT(old_level);

#if MEMP_OVERFLOW_CHECK >= 2
  memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK >= 2 */

//  printf("memp_type = %d \n", type);
//  printf("MEMP_LWBT_MAX = %d \n", MEMP_LWBT_MAX);

  memp = memp_tab[type];
  //printf("MEMP_TAB[TYPE=%d]\n", type);
  if (memp != NULL) {    
    //printf("here... (!=NULL)\n");
    memp_tab[type] = memp->next;    

#if MEMP_OVERFLOW_CHECK
    memp->next = NULL;
    memp->file = file;
    memp->line = line;
#endif // MEMP_OVERFLOW_CHECK
#if MEMP_STATS
    ++lwip_stats.memp[type].used;
    if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
      lwip_stats.memp[type].max = lwip_stats.memp[type].used;
    }
#endif // MEMP_STATS
    LWIP_ASSERT("memp_malloc: memp properly aligned",
                ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);

//printf("   (before) memp = %d ", (int) memp);
    memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
//printf("   (after) memp = %d \n", (int) memp);

  } else {
    LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
    //printf("memp_malloc: out of memory in pool %d\n", type);
#if MEMP_STATS
    ++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */
    memp_free(type, memp_tab[type-1]);
    memp = memp_tab[type];
      //printf("Again: MEMP_TAB[TYPE=%d]\n", type);
      if (memp == NULL) { return NULL;}
  }

  SYS_ARCH_UNPROTECT(old_level);

  return memp;
}

/**
 * Put an element back into its pool.
 *
 * @param type the pool where to put mem
 * @param mem the memp element to free
 */
void
memp_free(memp_t type, void *mem)
{
  struct memp *memp;
  SYS_ARCH_DECL_PROTECT(old_level);

  if (mem == NULL) {
    return;
  }
  LWIP_ASSERT("memp_free: mem properly aligned",
                ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);

  memp = (struct memp *)((u8_t*)mem - MEMP_SIZE);

  SYS_ARCH_PROTECT(old_level);
#if MEMP_OVERFLOW_CHECK
#if MEMP_OVERFLOW_CHECK >= 2
  memp_overflow_check_all();
#else
  memp_overflow_check_element(memp, memp_sizes[type]);
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#endif /* MEMP_OVERFLOW_CHECK */

#if MEMP_STATS
  lwip_stats.memp[type].used--; 
#endif /* MEMP_STATS */
  
  memp->next = memp_tab[type]; 
  memp_tab[type] = memp;

#if MEMP_SANITY_CHECK
  LWIP_ASSERT("memp sanity", memp_sanity());
#endif /* MEMP_SANITY_CHECK */

  SYS_ARCH_UNPROTECT(old_level);
}

